package com.ufo5260987423.graphDatabase.client;

import clojure.lang.IFn;
import clojure.lang.RT;
import clojure.lang.Symbol;
import com.ufo5260987423.graphDatabase.client.utils.GraphEdge;
import com.ufo5260987423.graphDatabase.client.utils.GraphNode;

import java.util.List;
import java.util.Map;

/**
 * Created by ufo on 5/18/15.
 */
public class REPL_Connector {

    public static REPL_Connector repl_connector_instance = null;

    private static IFn useFn = RT.var("clojure.core", "use").fn();
    private IFn eval_string = null;
    private IFn java_clojure_for_graph_node=null;
    private IFn java_clojure_for_graph_edge=null;
    private IFn save_node=null;
    private IFn save_edge=null;

    public Object evalString(String target){
        return this.getEval_string().invoke(target);
    }

    public GraphNode getGraphNodeBy(Integer graphNodeId){
        return (GraphNode)this.evalString("(clojure-java-for-graph-node (get-node "+graphNodeId+"))");
    }

    public List<GraphNode> searchGraphNodeBy(String nodeAttributeName,String nodeAttributeValue){
        return (List<GraphNode>)this.evalString(
                "(map clojure-java-for-graph-node " +
                "(search-graph-node-by \""+nodeAttributeName+
                "\" \""+nodeAttributeValue+"\"))");
    }

    public Integer saveGraphNode(GraphNode graphNode){
        return (Integer) this.getSave_node().invoke(
                this.getJava_clojure_for_graph_node().invoke(graphNode));
    }

    public Map<Integer,Long> saveGraphEdge(GraphEdge graphEdge){
        return (Map<Integer,Long>)this.getSave_edge().invoke(
                this.getJava_clojure_for_graph_edge().invoke(graphEdge));
    }

    public void deleteGraphNode(Integer graphNodeId){
        this.evalString("(delete-node "+graphNodeId+")");
    }

    public void connect(String ip,Integer port){
        this.loadConf();
        this.evalString("(use-database \""+ip+"\" (Integer. "+port+"))");
    }

    public void close(){
        this.evalString("(close-database)");
    }

    private void loadConf() {
        System.err.println("repl_connector loading");
        repl_connector_instance = this;

        useFn.invoke(Symbol.intern("com.ufo5260987423.graphDatabase.client.clojure.core"));
        useFn.invoke(Symbol.intern("com.ufo5260987423.graphDatabase.client.clojure.gao"));

        this.setSave_node(RT.var("com.ufo5260987423.graphDatabase.client.clojure.core", "save-node"));
        this.setSave_edge(RT.var("com.ufo5260987423.graphDatabase.client.clojure.core", "save-edge"));
        this.setEval_string(RT.var("com.ufo5260987423.graphDatabase.client.utils", "eval-string"));
        this.setJava_clojure_for_graph_node(RT.var("com.ufo5260987423.graphDatabase.client.clojure.gao", "java-clojure-for-graph-node"));
        this.setJava_clojure_for_graph_edge(RT.var("com.ufo5260987423.graphDatabase.client.clojure.gao", "java-clojure-for-graph-edge"));
    }

    public IFn getEval_string() {
        return eval_string;
    }

    public void setEval_string(IFn eval_string) {
        this.eval_string = eval_string;
    }

    public IFn getJava_clojure_for_graph_node() {
        return java_clojure_for_graph_node;
    }

    public void setJava_clojure_for_graph_node(IFn java_clojure_for_graph_node) {
        this.java_clojure_for_graph_node = java_clojure_for_graph_node;
    }

    public IFn getJava_clojure_for_graph_edge() {
        return java_clojure_for_graph_edge;
    }

    public void setJava_clojure_for_graph_edge(IFn java_clojure_for_graph_edge) {
        this.java_clojure_for_graph_edge = java_clojure_for_graph_edge;
    }

    public IFn getSave_edge() {
        return save_edge;
    }

    public void setSave_edge(IFn save_edge) {
        this.save_edge = save_edge;
    }

    public IFn getSave_node() {
        return save_node;
    }

    public void setSave_node(IFn save_node) {
        this.save_node = save_node;
    }
}
